﻿using DotNetCore.CAP;
using Microsoft.Extensions.Configuration;
using MT.Enterprise.Utils.Extensions;
using NP.BPMReportPlatform.Common;
using NP.BPMReportPlatform.Contract.Dtos;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.EmailHelper;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Engine;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.FlowManagement;
using NP.BPMReportPlatform.FlowManagement.Dto;
using NP.BPMReportPlatform.RecurringJobs;
using NP.BPMReportPlatform.RecurringJobs.Dto;
using NP.BPMReportPlatform.UserTrial.Enum;
using Serilog;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace NP.BPMReportPlatform.UserTrial
{
    public class UserTrialSyncJob : BpmReportPlatformRecurringJob, IUserTrialSyncJob
    {
        private readonly SqlSugarClient _db, _dbPlatform, _dbEngine;
        private readonly ICommonService _commonService;
        private readonly IEmailAPPService _emailAPPService;
        private readonly IFlowManagementAppService _flowManagementAppService;
        private readonly ICapPublisher _capBus;
        private readonly ILogger _logger;

        public UserTrialSyncJob(ISqlSugarAppService sqlSugarAppService,
            IConfiguration configuration, ICommonService commonService, IEmailAPPService emailAPPService,
            IFlowManagementAppService flowManagementAppService, ICapPublisher capBus, ILogger logger)
        {
            _db = sqlSugarAppService.GetBusinessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _commonService = commonService;
            _emailAPPService = emailAPPService;
            _dbEngine = sqlSugarAppService.GetEngineInstance();
            _flowManagementAppService = flowManagementAppService;
            _capBus = capBus;
            _logger = logger;
        }

        /// <summary>
        /// 1.试用期期间的流程，超过5天未提交，需要进行催办(这个交给别的定时任务  AutoFlowUrgingOverdueAsync)
        /// 2.邮件通知HRBP（提供邮件模版，每个月1号，16号，早上9点 各发一次）
        /// 3.新员工入职超过 3 天仍未安排导师，HRBP 会收到录入导师的邮件提醒
        /// 4.试用期到期前35天，45天提醒HRBP进行转正流程发起(提供模版)
        /// </summary>
        /// <returns></returns>
        public async Task SyncSendEmail()
        {
            await UserTrialJob1();
            await UserTrialJob2();
            await UserTrialJob3();
        }

        public async Task SyncFlowUrging()
        {
            await UserTrialJob4();
        }

        /// <summary>
        /// 1.试用期期间的流程，超过5天未提交，需要进行催办(这个交给别的定时任务  AutoFlowUrgingOverdueAsync)
        /// 2.邮件通知HRBP（提供邮件模版，每个月1号，16号，早上9点 各发一次）
        /// </summary>
        /// <returns></returns>
        private async Task UserTrialJob1()
        {
            if (DateTime.Now.Day == 1 || DateTime.Now.Day == 16)
            {
                DateTime lasttime = DateTime.Now.AddDays(-5);
                var btids = new List<string>() { "SYQJH", "SYQZJ", "SYQZZ", "ZBSYQZZ" };
                List<string> query = _dbEngine
                   .Queryable<Instances, InstanceStates>((it, its) => it.InstanceId == its.InstanceId)
                   .Where((it, its) => its.Status == 1)
                   .Where((it, its) => btids.Contains(it.BTID))
                   .Where((it, its) => its.LatestActivityName != "开始")
                   .Where((it, its) => its.LatestArriveTime < lasttime)
                   .Select((it, its) =>
                       it.Number
                  ).Distinct().ToList();

                var needShowMessages = _db.Queryable<TrialUsers>()
                    .Where(t => (query.Contains(t.DrawRound1) || query.Contains(t.DrawRound2)
                    || query.Contains(t.DrawRound3) || query.Contains(t.DrawRound4)
                    || query.Contains(t.ResultRound1) || query.Contains(t.ResultRound2)
                    || query.Contains(t.ResultRound3) || query.Contains(t.ResultRound4)
                    || query.Contains(t.Round5)) && t.Status < 6).Select(t => t).ToList();
                var allUsers = _dbPlatform.Queryable<Users>().Where(x => x.Status == 1).ToList();
                // 排除已离职人员
                needShowMessages = needShowMessages.Where(x => allUsers.Select(q => q.WorkNumber).Contains(x.WorkNumber)).ToList();
                query = query.Where(x =>
                    needShowMessages.Select(q => q.DrawRound1).Contains(x) ||
                    needShowMessages.Select(q => q.DrawRound2).Contains(x) ||
                    needShowMessages.Select(q => q.DrawRound3).Contains(x) ||
                    needShowMessages.Select(q => q.DrawRound4).Contains(x) ||
                    needShowMessages.Select(q => q.ResultRound1).Contains(x) ||
                    needShowMessages.Select(q => q.ResultRound2).Contains(x) ||
                    needShowMessages.Select(q => q.ResultRound3).Contains(x) ||
                    needShowMessages.Select(q => q.ResultRound4).Contains(x) ||
                    needShowMessages.Select(q => q.Round5).Contains(x)).ToList();

                _logger.Error($"UserTrialSyncJob.SyncSendEmail.UserTrialJob1.query Count:{query.Count}");
                _logger.Error($"UserTrialSyncJob.SyncSendEmail.UserTrialJob1.needShowMessages Count:{needShowMessages.Count}");
                if (query.Any() && needShowMessages.Count() > 0)
                {
                    List<string> allDeptCodes = new List<string>();
                    var alluserworkers = needShowMessages.Select(t => t.WorkNumber).ToList();
                    var allDeptFullPathCodes = allUsers.Where(t => alluserworkers.Contains(t.WorkNumber)).Select(t => t.FullPathCode).ToList();
                    allDeptFullPathCodes?.ForEach(t =>
                    {
                        allDeptCodes.AddRange(t.Split("_").ToList());
                    });

                    allDeptCodes = allDeptCodes.Distinct().ToList();

                    // 找到这些人对应的HRBP负责人(反向查找难哦)
                    var allworkNumbers = _dbPlatform.Queryable<SFPositionUserRelEntity, SFApproverEntity>((a, b) => a.PositionCode == b.PositionCode)
                        .Where((a, b) => allDeptCodes.Contains(b.DeptCode) && !string.IsNullOrEmpty(b.DeptCode)
                        && b.RoleCode == "HRBPPermission").Select((a, b) => a.UserId).Distinct().ToList();

                    // 给每个人发邮件
                    foreach (var item in allworkNumbers)
                    {
                        await this.SendEmail("2", item, needShowMessages, query);
                    }
                }
            }
        }

        /// <summary>
        /// 3.新员工入职超过 3 天仍未安排导师，HRBP 会收到录入导师的邮件提醒
        /// </summary>
        /// <returns></returns>
        private async Task UserTrialJob2()
        {
            var date = DateTime.Now.AddDays(-3);
            var needShowMessages = _db.Queryable<TrialUsers>()
                         .Where(t => t.TU && string.IsNullOrEmpty(t.HighMentorCode) && string.IsNullOrEmpty(t.MentorCode) && t.Status < 6)
                         .Where(t => t.JoinDate <= date)
                         .Select(t => t).ToList();
            var allUsers = _dbPlatform.Queryable<Users>().Where(x => x.Status == 1).ToList();
            needShowMessages = needShowMessages.Where(x => allUsers.Select(q => q.WorkNumber).Contains(x.WorkNumber)).ToList();

            if (needShowMessages.Count() > 0)
            {
                List<string> allDeptCodes = new List<string>();
                var alluserworkers = needShowMessages.Select(t => t.WorkNumber).ToList();
                var allDeptFullPathCodes = allUsers.Where(t => alluserworkers.Contains(t.WorkNumber)).Select(t => t.FullPathCode).ToList();
                allDeptFullPathCodes?.ForEach(t =>
                {
                    allDeptCodes.AddRange(t.Split("_").ToList());
                });

                allDeptCodes = allDeptCodes.Distinct().ToList();

                // 找到这些人对应的HRBP负责人(反向查找难哦)
                var allworkNumbers = _dbPlatform.Queryable<SFPositionUserRelEntity, SFApproverEntity>((a, b) => a.PositionCode == b.PositionCode)
                    .Where((a, b) => allDeptCodes.Contains(b.DeptCode) && !string.IsNullOrEmpty(b.DeptCode)
                    && b.RoleCode == "HRBPPermission").Select((a, b) => a.UserId).Distinct().ToList();

                // 给每个人发邮件
                foreach (var item in allworkNumbers)
                {
                    await this.SendEmail("3", item, needShowMessages);
                }
            }
        }

        /// <summary>
        ///  4.试用期到期前35天，45天提醒HRBP进行转正流程发起(提供模版)
        /// </summary>
        /// <returns></returns>
        private async Task UserTrialJob3()
        {
            DateTime date = DateTime.Now.AddDays(60);
            DateTime startdate = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0);
            DateTime enddate = startdate.AddDays(1).AddMinutes(-1);

            DateTime date1 = DateTime.Now.AddDays(45);
            DateTime startdate1 = new DateTime(date1.Year, date1.Month, date1.Day, 0, 0, 0);
            DateTime enddate1 = startdate1.AddDays(1).AddMinutes(-1);

            List<string> allDeptCodes = new List<string>();

            // 找到第45天和第60天的试用期人员
            var allUsers = _db.Queryable<TrialUsers>()
                           .Where(t => (t.RegularDate >= startdate && t.RegularDate <= enddate)
                           || (t.RegularDate >= startdate1 && t.RegularDate <= enddate1))
                           .Where(t => string.IsNullOrEmpty(t.Round5) && t.Status < 6)
                           .Select(t => t).Distinct().ToList();

            var allInUsers = _dbPlatform.Queryable<Users>().Where(x => x.Status == 1).ToList();
            allUsers = allUsers.Where(x => allInUsers.Select(q => q.WorkNumber).Contains(x.WorkNumber)).ToList();

            if (allUsers != null && allUsers.Count() > 0)
            {
                var alluserworkers = allUsers.Select(t => t.WorkNumber).ToList();
                var allDeptFullPathCodes = allInUsers.Where(t => alluserworkers.Contains(t.WorkNumber)).Select(t => t.FullPathCode).ToList();
                allDeptFullPathCodes?.ForEach(t =>
                {
                    allDeptCodes.AddRange(t.Split("_").ToList());
                });

                allDeptCodes = allDeptCodes.Distinct().ToList();

                // 找到这些人对应的HRBP负责人
                var allworkNumbers = _dbPlatform.Queryable<SFPositionUserRelEntity, SFApproverEntity>((a, b) => a.PositionCode == b.PositionCode)
                    .Where((a, b) => allDeptCodes.Contains(b.DeptCode) && !string.IsNullOrEmpty(b.DeptCode)
                    && b.RoleCode == "HRBPPermission").Select((a, b) => a.UserId).Distinct().ToList();

                // 给每个人发邮件
                foreach (var item in allworkNumbers)
                {
                    await this.SendEmail("4", item, allUsers);
                }
            }
        }

        /// <summary>
        ///  分离UserTrialJob1中的催办功能，每天早上8点催办
        /// </summary>
        /// <returns></returns>
        private async Task UserTrialJob4()
        {
            DateTime lasttime = DateTime.Now.AddDays(-5);
            DateTime limitime = DateTime.Now.AddMonths(-7);// 7个月之前的数据不再催办
            var btids = new List<string>() { "SYQJH", "SYQZJ", "SYQZZ", "ZBSYQZZ" };
            List<string> query = _dbEngine
               .Queryable<Instances, InstanceStates>((it, its) => it.InstanceId == its.InstanceId)
               .Where((it, its) => its.Status == 1)
               .Where((it, its) => btids.Contains(it.BTID))
               .Where((it, its) => its.LatestActivityName != "开始")
               .Where((it, its) => its.LatestArriveTime < lasttime && its.LatestArriveTime > limitime)
               .Select((it, its) =>
                   it.Number
              ).Distinct().ToList();

            var needShowMessages = _db.Queryable<TrialUsers>()
                .Where(t => (query.Contains(t.DrawRound1) || query.Contains(t.DrawRound2)
                || query.Contains(t.DrawRound3) || query.Contains(t.DrawRound4)
                || query.Contains(t.ResultRound1) || query.Contains(t.ResultRound2)
                || query.Contains(t.ResultRound3) || query.Contains(t.ResultRound4)
                || query.Contains(t.Round5)) && t.Status < 6).Select(t => t).ToList();
            var allUsers = _dbPlatform.Queryable<Users>().Where(x => x.Status == 1).ToList();
            // 排除已离职人员
            needShowMessages = needShowMessages.Where(x => allUsers.Select(q => q.WorkNumber).Contains(x.WorkNumber)).ToList();
            query = query.Where(x =>
                needShowMessages.Select(q => q.DrawRound1).Contains(x) ||
                needShowMessages.Select(q => q.DrawRound2).Contains(x) ||
                needShowMessages.Select(q => q.DrawRound3).Contains(x) ||
                needShowMessages.Select(q => q.DrawRound4).Contains(x) ||
                needShowMessages.Select(q => q.ResultRound1).Contains(x) ||
                needShowMessages.Select(q => q.ResultRound2).Contains(x) ||
                needShowMessages.Select(q => q.ResultRound3).Contains(x) ||
                needShowMessages.Select(q => q.ResultRound4).Contains(x) ||
                needShowMessages.Select(q => q.Round5).Contains(x)).ToList();

            _logger.Error($"UserTrialSyncJob.SyncFlowUrging.UserTrialJob4.query Count:{query.Count}");
            _logger.Error($"UserTrialSyncJob.SyncFlowUrging.UserTrialJob4.needShowMessages Count:{needShowMessages.Count}");

            FlowUrgingInput input = new FlowUrgingInput();
            if (query.Any())
            {
                foreach (var item2 in query)
                {
                    input.InstanceNumber = item2;
                    // 太多了，每个睡眠0.5s吧
                    Thread.Sleep(500);
                    await _flowManagementAppService.FlowUrgingAsync(input);
                }
            }
        }

        public async Task<string> GetFlowUrgingDataCount()
        {
            DateTime lasttime = DateTime.Now.AddDays(-5);
            DateTime limitime = DateTime.Now.AddMonths(-7);// 7个月之前的数据不再催办
            var btids = new List<string>() { "SYQJH", "SYQZJ", "SYQZZ", "ZBSYQZZ" };
            List<string> query = _dbEngine
               .Queryable<Instances, InstanceStates>((it, its) => it.InstanceId == its.InstanceId)
               .Where((it, its) => its.Status == 1)
               .Where((it, its) => btids.Contains(it.BTID))
               .Where((it, its) => its.LatestActivityName != "开始")
               .Where((it, its) => its.LatestArriveTime < lasttime && its.LatestArriveTime > limitime)
               .Select((it, its) =>
                   it.Number
              ).Distinct().ToList();

            var needShowMessages = _db.Queryable<TrialUsers>()
                .Where(t => (query.Contains(t.DrawRound1) || query.Contains(t.DrawRound2)
                || query.Contains(t.DrawRound3) || query.Contains(t.DrawRound4)
                || query.Contains(t.ResultRound1) || query.Contains(t.ResultRound2)
                || query.Contains(t.ResultRound3) || query.Contains(t.ResultRound4)
                || query.Contains(t.Round5)) && t.Status < 6).Select(t => t).ToList();
            var allUsers = _dbPlatform.Queryable<Users>().Where(x => x.Status == 1).ToList();
            // 排除已离职人员
            needShowMessages = needShowMessages.Where(x => allUsers.Select(q => q.WorkNumber).Contains(x.WorkNumber)).ToList();
            query = query.Where(x =>
                needShowMessages.Select(q => q.DrawRound1).Contains(x) ||
                needShowMessages.Select(q => q.DrawRound2).Contains(x) ||
                needShowMessages.Select(q => q.DrawRound3).Contains(x) ||
                needShowMessages.Select(q => q.DrawRound4).Contains(x) ||
                needShowMessages.Select(q => q.ResultRound1).Contains(x) ||
                needShowMessages.Select(q => q.ResultRound2).Contains(x) ||
                needShowMessages.Select(q => q.ResultRound3).Contains(x) ||
                needShowMessages.Select(q => q.ResultRound4).Contains(x) ||
                needShowMessages.Select(q => q.Round5).Contains(x)).ToList();

            return $"query Count Is {query.Count};needShowMessages Count Is {needShowMessages.Count}";
        }

        /// <summary>
        /// 发送邮件
        /// </summary>
        /// <param name="emailType">邮件类型</param>
        /// <param name="userName">发起人</param>
        /// <param name="workNumber">发起人工号</param>
        /// <param name="contractCode">合同编码</param>
        /// <returns></returns>
        private async Task SendEmail(string emailType, string workNumber, List<TrialUsers> trialUsers, List<string> exceptionInstances = null)
        {
            var topic = string.Empty;
            var templateName = string.Empty;
            var replaceContent = string.Empty;
            var content = string.Empty;
            string expInstanceNumbers = string.Empty;

            // 默认给发起人
            string to = string.Empty;
            if (!string.IsNullOrEmpty(workNumber))
            {
                to = _dbPlatform.Queryable<Users>().Where(t => t.WorkNumber == workNumber).First()?.Email;
            }
            #region 拼接邮件内容
            switch (emailType)
            {
                // 2.邮件通知HRBP（提供邮件模版，每个月1号，16号，早上9点 各发一次）
                case "2":
                    {
                        topic = "[系统邮件，请勿回复]超过5天未审批试用期流程清单";
                        templateName = "UnApprovedUserTrialProcess.cshtml";
                        var allworkNumbers = _commonService.GetUserByRoleFilter(workNumber, RelationshipTypeEnum.HRBP, true);
                        var allUserTrials = trialUsers.Where(p => allworkNumbers.Contains(p.WorkNumber)).ToList();
                        if (allUserTrials == null || allUserTrials.Count() == 0)
                        {
                            return;
                        }

                        allUserTrials?.ForEach(x =>
                        {
                            expInstanceNumbers = string.Empty;
                            if (exceptionInstances != null)
                            {
                                expInstanceNumbers = string.Join(",", exceptionInstances.Where(t => t == x.DrawRound1 || t == x.DrawRound2 || t == x.DrawRound3 || t == x.DrawRound4
                                || t == x.ResultRound1 || t == x.ResultRound2 || t == x.ResultRound3 || t == x.ResultRound4 || t == x.Round5).Take(2).ToList());
                            }
                            replaceContent += @$"<tr>
                                                 <th>{x.UserName}</th>   
                                                 <th>{x.WorkNumber}</th>
                                                 <th>{EnumExtension.GetDescription(typeof(TrialUserRoundEnum), x.Status ?? 0)}</th>  
                                                 <th>{x.JoinDate.Value.ToString("yyyy-MM-dd")}</th> 
                                                 <th>{x.RegularDate.Value.ToString("yyyy-MM-dd")}</th> 
                                                 <th>{x.ManageName}</th> 
                                                 <th>{x.IntervalManageName}</th> 
                                                 <th>{x.MentorName}</th> 
                                                 <th>{x.HighMentorName}</th> 
                                                 <th>{x.FullPathText}</th>     
                                                 <th>{expInstanceNumbers}</th>                       
                                                 </tr>";
                        });
                    }
                    break;
                // 3.新员工入职超过 3 天仍未安排导师，HRBP 会收到录入导师的邮件提醒
                case "3":
                    {
                        topic = "[系统邮件，请勿回复]入职3天未设置导师人员清单";
                        templateName = "UnSetMentorEmail.cshtml";
                        var allworkNumbers = _commonService.GetUserByRoleFilter(workNumber, RelationshipTypeEnum.HRBP, true);
                        var allUserTrials = trialUsers.Where(p => allworkNumbers.Contains(p.WorkNumber)).ToList();
                        if (allUserTrials == null || allUserTrials.Count() == 0)
                        {
                            return;
                        }

                        allUserTrials?.ForEach(x =>
                        {
                            replaceContent += @$"<tr>
                                                 <th>{x.UserName}</th>   
                                                 <th>{x.WorkNumber}</th>
                                                 <th>{EnumExtension.GetDescription(typeof(TrialUserRoundEnum), x.Status ?? 0)}</th>  
                                                 <th>{x.JoinDate.Value.ToString("yyyy-MM-dd")}</th> 
                                                 <th>{x.RegularDate.Value.ToString("yyyy-MM-dd")}</th> 
                                                 <th>{x.ManageName}</th> 
                                                 <th>{x.IntervalManageName}</th> 
                                                 <th>{x.FullPathText}</th>     
                                                 </tr>";
                        });
                    }
                    break;
                // 4.试用期到期前35天，45天提醒HRBP进行转正流程发起
                case "4":
                    {
                        topic = $"[系统邮件，请勿回复]试用期到期转正提醒";
                        templateName = "UnTripUserTrial.cshtml";

                        var allworkNumbers = _commonService.GetUserByRoleFilter(workNumber, RelationshipTypeEnum.HRBP, true);
                        var allUserTrials = trialUsers.Where(p => allworkNumbers.Contains(p.WorkNumber)).ToList();
                        if (allUserTrials == null || allUserTrials.Count() == 0)
                        {
                            return;
                        }

                        allUserTrials?.ForEach(x =>
                        {
                            replaceContent += @$"<tr>
                                                 <th>{x.UserName}</th>   
                                                 <th>{x.WorkNumber}</th>
                                                 <th>{EnumExtension.GetDescription(typeof(TrialUserRoundEnum), x.Status ?? 0)}</th>  
                                                 <th>{x.JoinDate.Value.ToString("yyyy-MM-dd")}</th> 
                                                 <th>{x.RegularDate.Value.ToString("yyyy-MM-dd")}</th> 
                                                 <th>{x.ManageName}</th> 
                                                 <th>{x.IntervalManageName}</th> 
                                                 <th>{x.MentorName}</th> 
                                                 <th>{x.HighMentorName}</th> 
                                                 <th>{x.FullPathText}</th>     
                                                 </tr>";
                        });
                    }
                    break;
            }
            #endregion
            if (!string.IsNullOrEmpty(templateName))
            {
                content = _emailAPPService.GenerateEmailTemplate(templateName);
                content = !string.IsNullOrEmpty(replaceContent) ?
                    content.Replace("{content}", replaceContent) : string.Empty;
            }
            if (!string.IsNullOrEmpty(content) && !string.IsNullOrEmpty(to))
            {
                await _capBus.PublishAsync("bpmnew.EmailAppService.SendEmailAsync",
                  new SendEmailSimpleDto()
                  {
                      To = to,//"tiger.zhou@movit-tech.com;liya.li@movit-tech.com",//, //TODO
                      Subject = topic,
                      Body = content
                  });
            }
        }
    }
}
